
/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  intl_cfg.h
 *         \unit  intl
 *        \brief  This is a simple large int number calculate module config header file for C language
 *       \author  Lamdonn
 *      \version  v1.0.0
 *      \license  GPL-2.0
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __intl_cfg_H
#define __intl_cfg_H

/* 
 * With this definition, you can configure the footprint size of an intl. 
 * This is a flexible definition that can be extended to larger numbers in addition to the given few size definitions
 */

/*****************************************************************/
/*                          Config start                         */
/*****************************************************************/
// #define INTL_USE_128BITS
// #define INTL_USE_256BITS
#define INTL_USE_512BITS
// #define INTL_USE_1024BITS
// #define INTL_USE_2048BITS
// #define INTL_USE_4096BITS
// #define INTL_USE_8192BITS

#if defined(INTL_USE_128BITS)
#define INTL_BIT_PARTS                      128
#define INTL_U32_PARTS                      4
#define INTL_U16_PARTS                      8
#define INTL_MAX_BIN                        129
#define INTL_MAX_DEC                        40
#define INTL_MAX_HEX                        33
#define INTL_MAX                            (intl){.u32={-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,}}
#elif defined(INTL_USE_256BITS)
#define INTL_BIT_PARTS                      256
#define INTL_U32_PARTS                      8
#define INTL_U16_PARTS                      16
#define INTL_MAX_BIN                        257
#define INTL_MAX_DEC                        78
#define INTL_MAX_HEX                        65
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,}}
#elif defined(INTL_USE_512BITS)
#define INTL_BIT_PARTS                      512
#define INTL_U32_PARTS                      16
#define INTL_U16_PARTS                      32
#define INTL_MAX_BIN                        513
#define INTL_MAX_DEC                        155
#define INTL_MAX_HEX                        129
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}}
#elif defined(INTL_USE_1024BITS)
#define INTL_BIT_PARTS                      1024
#define INTL_U32_PARTS                      32
#define INTL_U16_PARTS                      64
#define INTL_MAX_BIN                        1025
#define INTL_MAX_DEC                        309
#define INTL_MAX_HEX                        257
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}}    
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}}
#elif defined(INTL_USE_2048BITS)
#define INTL_BIT_PARTS                      2048
#define INTL_U32_PARTS                      64
#define INTL_U16_PARTS                      128
#define INTL_MAX_BIN                        2049
#define INTL_MAX_DEC                        618
#define INTL_MAX_HEX                        513
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}}
#elif defined(INTL_USE_4096BITS)
#define INTL_BIT_PARTS                      4096
#define INTL_U32_PARTS                      128
#define INTL_U16_PARTS                      256
#define INTL_MAX_BIN                        4097
#define INTL_MAX_DEC                        1234
#define INTL_MAX_HEX                        1025
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}}
#elif defined(INTL_USE_8192BITS)
#define INTL_BIT_PARTS                      8192
#define INTL_U32_PARTS                      256
#define INTL_U16_PARTS                      512
#define INTL_MAX_BIN                        8193
#define INTL_MAX_DEC                        2468
#define INTL_MAX_HEX                        2049
#define INTL_MAX                            (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}}
#define INTL_MIN                            (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}}
#define INTL_ZERO                           (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}}
#endif
/*****************************************************************/
/*                          Config end                           */
/*****************************************************************/

#if 0
void intl_gen_cfg(uint32_t bits)
{
    if ((bits & (bits - 1)) != 0)
    {
        printf("[ERROR] `bits` not a power of 2\r\n");
        return;
    }

    if (bits < 128)
    {
        printf("[ERROR] `bits` too small\r\b");
        return;
    }

    printf("/*****************************************************************/\r\n");
    printf("/*                          Config start                         */\r\n");
    printf("/*****************************************************************/\r\n");

    for (uint32_t tb = 128; tb <= bits; tb <<= 1)
    {
        if (tb == bits) 
        {
            printf("#define INTL_USE_%uBITS\r\n", tb);
        }
        else  
        {
            printf("// #define INTL_USE_%uBITS\r\n", tb);
        }
    }
    printf("\r\n");

    intl temp;

    for (uint32_t tb = 128; tb <= bits; tb <<= 1)
    {
        if (tb == 128) 
        {
            printf("#if defined(INTL_USE_%uBITS)\r\n", tb);
        }
        
        else  
        {
            printf("#elif defined(INTL_USE_%uBITS)\r\n", tb);
        }

        uint32_t BIT_PARTS ; /* bits */
        uint32_t U32_PARTS ; /* INTL_BIT_PARTS / 32 */
        uint32_t U16_PARTS ; /* INTL_BIT_PARTS / 16 */
        uint32_t MAX_BIN   ; /* INTL_BIT_PARTS + 1 */
        uint32_t MAX_DEC   ; /* strlen(intl_shl(intl(1), INTL_BIT_PARTS - 1)) + 1 */
        uint32_t MAX_HEX   ; /* INTL_BIT_PARTS / 4 + 1 */

        BIT_PARTS = tb;
        U32_PARTS = BIT_PARTS >> (5);
        U16_PARTS = BIT_PARTS >> (4);
        MAX_BIN = BIT_PARTS + 1;
        MAX_DEC = MAX_BIN;
        MAX_HEX = (BIT_PARTS >> (2)) + 1;

        if (sizeof(temp) == (bits >> 3))
        {
            char buffer[INTL_MAX_BIN];
            MAX_DEC = strlen(intl_sdec(intl_shl(intl(1), BIT_PARTS - 1), buffer)) + 1;
        }

        printf("#define INTL_BIT_PARTS                      %u\r\n", BIT_PARTS);
        printf("#define INTL_U32_PARTS                      %u\r\n", U32_PARTS);
        printf("#define INTL_U16_PARTS                      %u\r\n", U16_PARTS);
        printf("#define INTL_MAX_BIN                        %u\r\n", MAX_BIN);
        printf("#define INTL_MAX_DEC                        %u\r\n", MAX_DEC);
        printf("#define INTL_MAX_HEX                        %u\r\n", MAX_HEX);
        intl max = (intl){.u32={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0x7FFFFFFF,}};
        intl min = (intl){.u32={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80000000,}};
        printf("#define INTL_MAX                            (intl){.u32={");
        for (uint32_t i = 0; i < U32_PARTS; i++)
        {
            printf("%s,", (i == U32_PARTS-1) ? "0x7FFFFFFF" : "-1");
        }
        printf("}}\r\n");

        printf("#define INTL_MIN                            (intl){.u32={");
        for (uint32_t i = 0; i < U32_PARTS; i++)
        {
            printf("%s,", (i == U32_PARTS-1) ? "0x80000000" : "0");
        }
        printf("}}\r\n");

        printf("#define INTL_ZERO                           (intl){.u32={");
        for (uint32_t i = 0; i < U32_PARTS; i++)
        {
            printf("0,");
        }
        printf("}}\r\n");
    }

    printf("#endif\r\n");

    printf("/*****************************************************************/\r\n");
    printf("/*                          Config end                           */\r\n");
    printf("/*****************************************************************/\r\n");

    printf("\r\n\r\n-------------------------------------------------------------\r\n\r\n");

    if (sizeof(temp) != (bits >> 3))
    {
        printf("[TODO] Apply the current configuration and run it again to get the new `INTL_MAX_DEC`\r\n");
    }
    else  
    {
        printf("[INFO] The configuration has been generated, copy it to the `intl_cfg.h` range specified\r\n");
    }
}
#endif

#endif

